AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include('shared.lua')

function ENT:Initialize()
	// Constants
	me=self.Entity
	self.EngineSound="ambient/machines/diesel_engine_idle1.wav"
	self.IgnitionSound="ambient/energy/spark1.wav"

	// Precache shit
	util.PrecacheSound(self.EngineSound)
	util.PrecacheSound(self.IgnitionSound)
	
	// Get keyvalues and use them
	me:SetName(self.Entity["targetname"])
	if (self.Entity["parentname"]!=nil) then me:SetParent(self.Entity["parentname"]) end
	temp = self.Entity["worldmodel"] or "models/props_vehicles/generatortrailer01.mdl"
	me:SetModel(temp)
	tempangles = string.Explode(" ",self.Entity["angles"]) or {0, 0, 0}
	me:SetAngles(Angle(tempangles[1],tempangles[2],tempangles[3]))
	temp=tonumber(self.Entity["health"]) or 200
	me:SetHealth(temp)
	self.max_health = tonumber(self.Entity["max_health"]) or 200
	self.fuel = tonumber(self.Entity["fuel"]) or 1000
	self.max_fuel = tonumber(self.Entity["max_fuel"]) or 1000
	self.consumptionrate = tonumber(self.Entity["consumptionrate"]) or 1
	
	// Set some variables pertaining to death
	self.killquiet=false
	self.killer=nil
	self.killertime=0	
	
	// Get spawnflags and use them
	self.running=me:Flag(0)
	self.indestructable=me:Flag(1)
	self.silent=me:Flag(2)
	self.nofill=me:Flag(3)
	self.nosiphon=me:Flag(4)
	self.nomove=me:Flag(5)
		
	// Initalize physics
	if (self.Entity["parentname"]!=nil) then self.nomove=false end
	me:PhysicsInit(SOLID_VPHYSICS)
	if (self.nomove) then me:SetMoveType(MOVETYPE_NONE)
	else me:SetMoveType(MOVETYPE_VPHYSICS) end
	me:SetSolid(SOLID_VPHYSICS)
	local phys=me:GetPhysicsObject()
	if (phys:IsValid()) then phys:Wake() end
	
	// Set up the sound stuff
	self.TheEngineSound=CreateSound(me,self.EngineSound)
	self.PlayingEngineSound=false
	if (!self.silent) then
		self.NoiseTimer=CurTime()
		self.TheEngineSound:Play()
		self.PlayingEngineSound=true
	end
	
	// Set up the fuel stuff
	self.nextconsumption=1
	self.runninglast=false
	if (self.fuel<0) then
		self.running=false
		if (!self.silent) then self.TheEngineSound:Stop() end
	end
	
	// Prevent repeatedly calling outputs when something's happened
	self.Triggered = {}
	self.Triggered["OnHalfHealth"]=false
	self.Triggered["OnEmpty"]=false
	self.Triggered["OnActivate"]=false
	self.Triggered["OnDeactivate"]=false
end
function ENT:KeyValue(key, value)
	if (self.Entity:IsOutput(key)) then self.Entity:StoreOutput(key,value)
	else self.Entity[key]=value end
end
function ENT:AcceptInput(i, activator, caller)
	me=self.Entity
	if		(i=="Kill") then
		self.killquiet=true
		me:Remove()
	elseif	(i=="SetHealth") then
		me:SetHealth(v)
	elseif	(i=="AddHealth") then
		me:SetHealth(me:Health()+v)
	elseif	(i=="RemoveHealth") then
		me:SetHealth(me:Health()-v)
	elseif	(i=="SetMaxHealth") then
		self.max_health=v
	elseif	(i=="AddMaxHealth") then
		self.max_health=self.max_health+v
	elseif	(i=="RemoveMaxHealth") then
		self.max_health=self.max_health-v
	elseif	(i=="SetFuel") then
		self.fuel=v
	elseif	(i=="AddFuel") then
		self.fuel=self.fuel+v
	elseif	(i=="RemoveFuel") then
		self.fuel=self.fuel-v
	elseif	(i=="SetMaxFuel") then
		self.max_fuel=v
	elseif	(i=="AddMaxFuel") then
		self.max_fuel=self.max_fuel+v
	elseif	(i=="RemoveMaxFuel") then
		self.max_fuel=self.max_fuel-v
	elseif	(i=="Ignite") then
		me:Ignite()
	elseif	(i=="Break") then
		me:Remove()
	elseif	(i=="Activate") then
		self.running=true
	elseif	(i=="Deactivate") then
		self.running=false
	end
end
function ENT:Use(activator, caller)
	if (!self.nofill) then
		if (true) then // TODO: Replace "true" with the inventory system equivilant of "I have at least one fuel can"
			self:TriggerOutput("OnFill",NULL)
			if (CurTime()>=self.NoiseTimer and !self.silent) then
				me:EmitSound(self.IgnitionSound)
				self.NoiseTimer=CurTime()+3
				score.generators.refilled[activator:UserID()] = score.generators.refilled[activator:UserID()] + 1
				self.fuel=math.Clamp(self.fuel+2000,0,self.max_fuel)
				if (!self.running) then
					self.running=true
					self.nextconsumption=CurTime()+1
				end
			end
		end
	else
		// tell then that they couldn't fill it here
	end
end
function ENT:Think()
	me=self.Entity
	
	// Ignition sound, OnActivate, OnDeactivate
	if (self.runninglast!=self.running) then
		// OnActivate
		if (self.running) then
			if (!self.Triggered["OnActivate"]) then
				self:TriggerOutput("OnActivate",NULL)
				self.Triggered["OnActivate"]=true
			end
		else
			self.Triggered["OnActivate"]=false
		end
		
		// OnDeactivate
		if (!self.running) then
			if (!self.Triggered["OnDeactivate"]) then
				self:TriggerOutput("OnDeactivate",NULL)
				self.Triggered["OnDeactivate"]=true
			end
		else
			self.Triggered["OnDeactivate"]=false
		end
		
		if (!self.silent) then me:EmitSound(self.IgnitionSound) end
		self.runninglast=self.running
	end
	
	// Engine sounds
	if (!self.silent) then
		if (self.running) then
			if (!self.PlayingEngineSound) then
				self.TheEngineSound:Play()
				self.PlayingEngineSound=true
			end
		else
			if (self.PlayingEngineSound) then
				self.TheEngineSound:Stop()
				self.PlayingEngineSound=false
			end
		end
	end
	
	// Tooltip
	//self:SetOverlayText(self:ObscureHealth()..", "..self:ObscureFuel())
	
	// Fuel consumption
	if (self.nextconsumption<CurTime() and self.running) then
		self.fuel=self.fuel-self.consumptionrate
		if (self.fuel==0) then
			if (!self.Triggered["OnEmpty"]) then
				self:TriggerOutput("OnEmpty",NULL)
				self.Triggered["OnEmpty"]=true
			end
			self.running=false
		else
			self.nextconsumption=CurTime()+1
			self.Triggered["OnEmpty"]=false
		end
	end
	
	// OnHalfHealth
	if (me:Health()<=(self.max_health/2)) then
		if (!self.Triggered["OnHalfHealth"]) then
			self:TriggerOutput("OnHalfHealth",NULL)
			self.Triggered["OnHalfHealth"]=true
		end
	else
		self.Triggered["OnHalfHealth"]=false
	end
end
function ENT:OnTakeDamage(dmg)
	self:TriggerOutput("OnDamaged",dmg:GetAttacker())
	if (!self.invulnerable) then
		me=self.Entity
		me:SetHealth(me:Health()-dmg:GetDamage())
		if (math.Round((me:Health()/self.max_health)*100)<=25 and !me:IsOnFire()) then // barely intact
			me:Ignite(100,32)
		end
		if (dmg:GetInflictor():IsPlayer()) then
			self.killer=dmg:GetInflictor()
			self.killertime=CurTime()
		end
		if (me:Health()<=5) then
			if (self.killer!=nil and self.killertime+30>=CurTime()) then
				SendChatMessage( self.killer:GetName() .. " destroyed a generator.", CHAT_KILL )
				score.generators.destroyed[self.killer:UserID()] = score.generators.destroyed[self.killer:UserID()] + 1
			else
				SendChatMessage( "A generator was mysteriously destroyed...", CHAT_KILL )
			end
			me:Remove()
		end
	end
end
function ENT:OnRemove()
	self:TriggerOutput("OnDeath",NULL)
	self:TriggerOutput("OnDeactivate",NULL)
	if (!self.silent and self.PlayingEngineSound) then self.TheEngineSound:Stop() end
	if (!self.killsilent) then
		local effectdata=EffectData()
		effectdata:SetOrigin(me:GetPos())
		util.Effect("Explosion",effectdata)
		local ent = ents.Create("env_explosion")
		if (ent and ent!=NULL) then
			ent:SetOwner(self.Thrower)
			ent:SetKeyValue("iMagnitude","50")
			ent:SetPos(self.Entity:GetPos())
			ent:Spawn()
			ent:Activate()
			ent:Fire("Explode",0,0)
		end
	end
end

function ENT:ObscureFuel()
	if (!self.running) then return "powered down" end
	local p=math.Round((self.fuel/self.max_fuel)*100)
	local t=""
	if (p>90) then
		t="full tank"
	elseif (p>75) then
		t="three-quarters full"
	elseif (p>50) then
		t="half-full"
	elseif (p>25) then
		t="one-quarter full"
	elseif (p>0) then
		t="barely running"
	else
		t="empty"
	end
	return t
end
function ENT:ObscureHealth()
	local p=math.Round((me:Health()/self.max_health)*100)
	local t=""
	if (p>90) then
		t="Brand-new"
	elseif (p>75) then
		t="Slightly damaged"
	elseif (p>50) then
		t="Noticably damaged"
	elseif (p>25) then
		t="Severely damaged"
	elseif (p>0) then
		t="Barely intact"
	else
		t="Destroyed"
	end
	return t
end
function ENT:SetOverlayText(text)
	self.Entity:SetNetworkedString("GModOverlayText", text)
end
function ENT:GetOverlayText()
	local txt=self.Entity:GetNetworkedString( "GModOverlayText" )
	if (txt=="") then return "" end
	if (SinglePlayer()) then return txt end
	local PlayerName=self:GetPlayerName()
	return txt.."\n("..PlayerName..")"
end

function ENT:IsOutput(o)
	local OUTPUTLIST = { "OnDamaged", "OnDeath", "OnHalfHealth", "OnActivate", "OnDeactivate", "OnFill", "OnEmpty", "OnSiphon" }
	local r=false
	for i in pairs(OUTPUTLIST) do
		if (o==OUTPUTLIST[i]) then return true end
	end
	return false
end
